import { msgError } from '@/utils/message';

let CALL_TYPE = {
  AUDIO: 'call-audio',
  VIDEO: 'call-audiovideo',
  HALF_AUDIO: 'call-halfaudio',
  HALF_VIDEO: "call-halfvideo",
  LIVE: "call-live",
};

class Webrtc2Sip {
  static instances; // 已实例化的对象
  static globalSessionEvent; // 会话回调事件
  static globalStackEvent; // sip栈回调事件
  static globalCustomSessionEvent; // 自定义会话回调事件
  static globalCustomStackEvent; // 自定义sip栈回调事件
  static audioRemote; // 远程语音
  static isInited = false; // 是否初始化
  static webrtc2SipEnabled = false; // 是否启用

  // 获取已实例化的Webrtc2Sip对象
  static getInstances() {
    return [...this.instances.values()];
  }

  // 销毁Webrtc2Sip所有实例
  static destroy() {
    for (const item of this.instances.values()) {
      item.unRegister();
    }
  }

  /**
   * 构造函数
   * @param {*} containers
   * @param {*} sessionEvent
   */
  constructor(options) {
    this.videoRemote = null; // 远端视频
    this.videoLocal = null; // 本地视频
    this.webrtcStackNode = null;
    this.phone = null;
    this.password = null;
    this.websocketServer = null;
    this.iceservers = null;
    this.callType = null;
    this.login = true;
    this.called = null;
    this.requestTel = null;
    // 事件
    this.customSessionEvent = null;
    this.customStackEvent = null;

  }

  /**
   * 初始化
   * @param {Fuction} sessionEvent 会话回调事件
   * @param {Fuction} stackEvent sip栈回调事件
   * @param {String} debugLevel sip console日志等级
   */
  static init(sessionEvent, stackEvent, options) {
    // 检查是否支持WebRTC
    if (!checkSupportWebrtc()) {
      alert('当前浏览器不支持WebRTC,请使用谷歌/火狐浏览器');
      return;
    }
    // // 检查是否支持WebSocket
    // if (!checkSupportWebsocket()) {
    //   alert('当前浏览器不支持WebSocket');
    //   return;
    // }
    this.instances = new Map();
    this.setGlobalEvent(sessionEvent, stackEvent);
    this.audioRemote = document.getElementById(options.audioRemote) || null;
    this.videoRemote = document.getElementById(options.videoRemote) || null;
    this.videoLocal = document.getElementById(options.videoLocal) || null;

    this.isInited = true;
  }

  /**
   * 注册
   * @param {Object} options
   */
  register(options) {
    try {
      if (!options.phone) {
        msgError('号码不能为空');
        return false;
      }
      this.phone = options.phone;
      this.password = options.password;
      const protocol = location.protocol === 'https:' ? 'wss://' : 'ws://';
      this.websocketServer = protocol + `${location.host}/webrtc2sip_ws`;

      this.iceservers = options.iceServers ? options.iceServers.split(',') : [];

      if (this.iceservers.length > 0) {
        this.iceservers.forEach((item, index, array) => {
          array[index] = 'stun:' + item;
        });
      }

      if (this.webrtcStackNode != null) {
        this.webrtcStackNode.exit();
      }
      this.webrtcStackNode = new webrtcStack(
        this.websocketServer,
        this.phone,
        this.password,
        event => {
          this.webrtcstackCallback.call(this, event);
        },
        this.iceservers
      );
      Webrtc2Sip.instances.set(this.phone, this);
      Webrtc2Sip.webrtc2SipEnabled = true;
      this.name = this.phone; // webrtc2sip名称，用号码表示
      this.phoneType = options.phoneType; //号码类型 主手柄/副手柄
      return true;
    } catch (e) {
      console.log('register', e);
      this.webrtcStackNode = null;
      this.stackEventFun({
        type: 'failed_to_start',
        description: 'Stack failed_to_start',
      });
      return false;
    }
  }

  unRegister() {
    if (this.webrtcStackNode == null) {
      return;
    }

    this.webrtcStackNode.exit();

    Webrtc2Sip.instances.delete(this.name);
  }

  sipCall(callType, phoneNumber) {
    var hasVideo = false;
    var hasHalf = false;
    var local = null;
    var remote = null;

    if (this.webrtcStackNode == null) {
      return false;
    }

    if (!phoneNumber) {
      return false;
    }
    if (callType === CALL_TYPE.AUDIO) {
      this.callType = "audio";
      remote = this.audioRemote;
    } else if (callType === CALL_TYPE.HALF_AUDIO) {
      hasHalf = true;
      this.callType = "half/audio";
      remote = this.audioRemote;
    } else if (callType === CALL_TYPE.VIDEO) {
      this.callType = "audio/video";
      hasVideo = true;
      remote = this.videoRemote;
      local = this.videoLocal;
    } else if (callType === CALL_TYPE.HALF_VIDEO) {
      this.callType = "half/video";
      hasVideo = true;
      hasHalf = true;
      remote = this.videoRemote;
      local = this.videoLocal;
    } else if (callType === CALL_TYPE.LIVE) {
      this.callType = "half/video";
      hasVideo = true;
      hasHalf = true;
      remote = this.videoRemote;
    } else {
      return false;
    }
    this.sessionEventFun(
      {
        type: CALL_MESSAGE_TYPE.CONNECTING,
        description: 'Call in progress...',
      },
      'Call'
    );
    this.webrtcStackNode.call(phoneNumber, local, remote, hasVideo, hasHalf);
    return true;
  }

  sipHangUp() {
    if (this.webrtcStackNode == null) {
      return;
    }

    this.webrtcStackNode.hangup();
    return true;
  }

  sipAnswer(videoRemoteId, videoLocalId) {
    if (this.webrtcStackNode == null) {
      return false;
    }
    if (this.callType === 'audio/video') {
      this.webrtcStackNode.answer(
        document.getElementById(videoLocalId) || this.videoLocal,
        document.getElementById(videoRemoteId) || this.videoRemote
      );
    } else {
      this.webrtcStackNode.answer(null, Webrtc2Sip.audioRemote);
    }
    this.sessionEventFun({ type: 'connected', description: 'In Call' }, 'Call');
    return true;
  }

  sipRequest() {
    if (this.webrtcStackNode == null) {
      return;
    }

    this.webrtcStackNode.pttrequest();

    return true;
  }

  sipRelease() {
    if (this.webrtcStackNode == null) {
      return;
    }

    this.webrtcStackNode.pttrelease();
    return true;
  }

  sipDtmf(dtmfValue) {
    if (this.webrtcStackNode == null) {
      return;
    }

    this.webrtcStackNode.dtmf();
    return true;
  }

  /**
   * 播放video
   */
  playVideo() {
    try {
      console.log('webrtc playVideo', this.videoLocal, this.videoRemote);
      this.videoLocal && this.videoLocal.play();
      this.videoRemote && this.videoRemote.play();
    } catch (error) {
      console.log('playVideo', error);
    }
  }

  getCallType() {
    return this.callType;
  }

  getCallName() {
    return this.called ? this.called : '未知';
  }

  getRequestName() {
    return this.requestTel ? this.requestTel : '未知';
  }

  sessionEventFun(event, sessionType) {
    const sessionEvent =
      this.customSessionEvent ||
      Webrtc2Sip.globalCustomSessionEvent ||
      Webrtc2Sip.globalSessionEvent;
    sessionEvent(event, sessionType, this);
    // if (this.sessionEvent != null) {
    //   this.sessionEvent(event, sessionType);
    // }
  }

  stackEventFun(event) {
    const stackEvent =
      this.customStackEvent ||
      Webrtc2Sip.globalCustomStackEvent ||
      Webrtc2Sip.globalStackEvent;
    stackEvent(event, this);
  }

  webrtcstackCallback(msg) {
    switch (msg.type) {
      case CALL_MESSAGE_TYPE.STARTING:
      case CALL_MESSAGE_TYPE.STARTED:
        this.stackEventFun(msg);
        break;
      case CALL_MESSAGE_TYPE.CONNECTING:
        this.sessionEventFun(msg, 'Registration');
        break;
      case CALL_MESSAGE_TYPE.LOGIN:
        if (msg.result) {
          this.sessionEventFun(
            { type: 'connected', description: 'Connected' },
            'Registration'
          );
        } else {
          this.sessionEventFun(
            { type: 'terminated', description: '用户号码或密码错误' },
            'Registration'
          );
          sessionStorage.removeItem('userName')
          sessionStorage.removeItem('passWord')
        }
        break;
      case CALL_MESSAGE_TYPE.MAKECALL:
        this.sessionEventFun(
          { type: 'terminated', description: msg.reason },
          'Call'
        );
        break;
      case CALL_MESSAGE_TYPE.ONRING:
      case CALL_MESSAGE_TYPE.ONRING183:
        this.sessionEventFun(
          { type: 'i_ao_request', description: 'Ringing' },
          'Call'
        );
        break;
      case CALL_MESSAGE_TYPE.ONANSWER:
        this.sessionEventFun(
          { type: 'connected', description: 'In Call' },
          'Call'
        );
        break;
      case CALL_MESSAGE_TYPE.ONHANGUP:
        this.sessionEventFun(
          { type: 'terminated', description: '会议结束' },
          'Call'
        );
        break;
      case CALL_MESSAGE_TYPE.ONNEWCALL:
        this.called = msg.from;
        if (msg.isvideo) {
          this.callType = 'audio/video';
        } else if (msg.ishalf) {
          this.callType = 'half/audio';
        } else {
          this.callType = 'audio';
        }
        this.stackEventFun({
          type: 'i_new_call',
          description: 'Incoming Call',
        });
        break;
      case CALL_MESSAGE_TYPE.PTTREQUEST:
        if (msg.result) {
          this.sessionEventFun(
            { type: 'requested', description: 'requested' },
            'Call'
          );
        } else {
          this.sessionEventFun(
            { type: 'failed_to_request', description: 'failed_to_request' },
            'Call'
          );
        }
        break;
      case CALL_MESSAGE_TYPE.PTTRELEASE:
        this.sessionEventFun(
          { type: 'released', description: 'released' },
          'Call'
        );
        break;
      case CALL_MESSAGE_TYPE.ONPTTREQUEST:
        this.requestTel = msg.tel;
        this.sessionEventFun(
          { type: 'on_requested', description: msg.tel },
          'Call'
        );
        break;
      case CALL_MESSAGE_TYPE.ONPTTRELEASE:
        this.sessionEventFun(
          { type: 'on_released', description: 'on_released' },
          'Call'
        );
        break;
      case CALL_MESSAGE_TYPE.ONDISCONNECT:
        if (this.login) {
          this.login = false;
          this.stackEventFun({ type: 'stopped', description: 'Stack stopped' });
        } else {
          this.stackEventFun({
            type: 'failed_to_start',
            description: 'Failed to connet to the server',
          });
        }
        break;
      case CALL_MESSAGE_TYPE.MEETUSERS:
        this.sessionEventFun({ type: "meet_users", description: msg.content }, "Call");
        break;
    }
  }
  // 是否启用webrtc2sip
  static isEnabled() {
    return this.webrtc2SipEnabled;
  }
  /**
   * 根据号码判断是否启用
   * @param {String} name 号码
   */
  static isExistForName(name) {
    return this.getWebrtc2SipByName(name) ? true : false;
  }
  /**
   * 设置全局回调事件
   * @param {Functon} sessionEvent
   * @param {Functon} stackEvent
   */
  static setGlobalEvent(sessionEvent, stackEvent) {
    if (sessionEvent && stackEvent) {
      this.globalSessionEvent = sessionEvent;
      this.globalStackEvent = stackEvent;
    } else {
      throw new Error('session事件和stack事件必须同时存在');
    }
  }
  /**
   * 设置全局自定义回调事件
   * @param {Functon} sessionEvent
   * @param {Functon} stackEvent
   */
  static setGlobalCustomEvent(sessionEvent, stackEvent) {
    this.globalCustomSessionEvent = sessionEvent;
    this.globalCustomStackEvent = stackEvent;
  }
  /**
   * 通过号码获取webrt2sip对象
   * @param {String} name 号码
   */
  static getWebrtc2SipByName(name) {
    return this.instances.get(name);
  }
  /**
   * 通过号码清除自定义事件
   * @param {String} name 号码
   */
  static clearCustomEventByName(name) {
    const item = this.instances.get(name);
    if (item) item.clearCustomEvent();
  }
  /**
   * 设置自定义事件，优先级别高于全局事件，有自定义事件后不再调用全局事件，如需要调用可以在自定义事件里面用Webrtc2Sip类调用，
   * 注意：离开页面时需要清除自定义事件
   */
  setCustomEvent(sessionEvent, stackEvent) {
    if (sessionEvent && stackEvent) {
      this.customSessionEvent = sessionEvent;
      this.customStackEvent = stackEvent;
    } else {
      throw new Error('session事件和stack事件必须同时存在');
    }
  }

  /**
   * 清除自定义事件
   */
  clearCustomEvent() {
    this.customSessionEvent = null;
    this.customStackEvent = null;
  }
  /**
   * 设置video播放dom
   * @param {Dom} videoRemote 远程视频播放video元素id
   * @param {Dom} videoLocal  本地视频播放video元素id
   * @param {String} mudule  模块
   */
  setVideoDom(videoRemoteId, videoLocalId) {
    this.videoLocal = document.getElementById(videoLocalId);
    this.videoRemote = document.getElementById(videoRemoteId);
  }
  /**
   * 清除播放dom
   */
  clearVideoDom() {
    console.error('clearVideoDom');
    this.videoLocal = null;
    this.videoRemote = null;
  }
}

let CALL_MESSAGE_TYPE = {
  STARTING: 'starting',
  STARTED: 'started',
  CONNECTING: 'connecting',

  LOGIN: 'login',
  MAKECALL: 'make_call',
  RING: 'ring',
  ANSWER: 'answer',
  HANGUP: 'hangup',
  LOGOUT: 'logout',
  DTMF: 'dtmf',
  PTTREQUEST: 'ptt_request',
  PTTRELEASE: 'ptt_release',
  HEART: 'heart',
  MEETUSERS: "meet_users",

  ONNEWCALL: 'on_new_call',
  ONRING: 'on_ring',
  ONRING183: 'on_ring_183',
  ONANSWER: 'on_answer',
  ONHANGUP: 'on_hangup',
  ONPTTREQUEST: 'on_ptt_request',
  ONPTTRELEASE: 'on_ptt_release',

  ONDISCONNECT: 'on_disconnect',
};

let CALL_DIRECTION = {
  IN: 0,
  OUT: 1,
};

class webrtcStack {
  constructor(wsurl, tel, passwd, sessionEvent, iceservers) {
    if (!wsurl.endsWith('/')) {
      wsurl = wsurl + '/';
    }
    this.wsurl = wsurl + 'webrtcMedia';
    this.tel = tel;
    this.passwd = passwd;
    this.WSStatus = false;
    this.onMessage = sessionEvent;
    this.notify({ type: 'starting', description: 'Stack starting' });

    // this.WS = new ReconnectingWebSocket(this.wsurl);
    console.log('ws客户端', this.WS)
    this.WS = new WebSocket(this.wsurl);
    this.interval = null;
    if (iceservers.length > 0) {
      this.config = {
        iceServers: [{ urls: iceservers }],
      };
    } else {
      this.config = {
        iceServers: [],
      };
    }

    this.WS.onopen = () => {
      console.log('ws connect succ.', this.WS);
      this.notify({ type: 'started', description: 'Stack started' });
      this.WSStatus = true;
      this.notify({ type: 'connecting', description: 'connecting' });
      this.login();
    };
    this.WS.onclose = ev => {
      console.log('ws connect close.', ev);
      this.WSStatus = false;
      this.regStatus = false;
      this.callStatus = false;
      if (this.interval) {
        clearInterval(this.interval);
        this.interval = null;
      }
      this.notify({ type: CALL_MESSAGE_TYPE.ONDISCONNECT });
    };

    window.onbeforeunload = () => {
      this.WS.close();
      if (this.interval) {
        clearInterval(this.interval);
        this.interval = null;
      }
    };

    this.WS.onmessage = ev => {
      var recvmsg = JSON.parse(ev.data);
      console.log(recvmsg);
      switch (recvmsg.type) {
        case CALL_MESSAGE_TYPE.LOGIN:
          if (recvmsg.result && !this.regStatus) {
            this.regStatus = true;
          }
          if (!recvmsg.result) {
            this.WS.close();
          }
          this.notify({
            type: recvmsg.type,
            result: recvmsg.result,
            reason: recvmsg.reason === undefined ? '' : recvmsg.reason,
          });
          if (this.interval) {
            clearInterval(this.interval);
            this.interval = null;
          }
          this.interval = setInterval(() => this.heart(), 30000);
          break;
        // case CALL_MESSAGE_TYPE.LOGOUT:
        //     // this.regStatus = false;
        //     // this.notify({"type":recvmsg.type, "result":recvmsg.result, "reason":recvmsg.reason===undefined?"":recvmsg.reason});
        //     break;
        case CALL_MESSAGE_TYPE.PTTREQUEST:
        case CALL_MESSAGE_TYPE.PTTRELEASE:
          this.notify({ type: recvmsg.type, result: recvmsg.result });
          break;
        case CALL_MESSAGE_TYPE.ONPTTREQUEST:
          this.notify({
            type: recvmsg.type,
            tel: recvmsg.content === undefined ? '' : recvmsg.content,
          });
          break;
        case CALL_MESSAGE_TYPE.ONPTTRELEASE:
          this.notify({ type: recvmsg.type });
          break;
        case CALL_MESSAGE_TYPE.ONRING:
          this.ringbacktone.currentTime = 0;
          this.ringbacktone.play();
          this.notify({ type: recvmsg.type });
          break;
        case CALL_MESSAGE_TYPE.ONRING183:
          this.ringbacktone.pause();
          this.onanswer(recvmsg.sdp);
          this.notify({ type: recvmsg.type });
          break;
        case CALL_MESSAGE_TYPE.ONANSWER:
          this.ringbacktone.pause();
          this.onanswer(recvmsg.sdp);
          this.notify({ type: recvmsg.type });
          break;
        case CALL_MESSAGE_TYPE.ONHANGUP:
          this.notify({
            type: recvmsg.type,
            reason: recvmsg.reason === undefined ? '' : recvmsg.reason,
          });
          this.closeCall();
          this.ringtone.pause();
          this.ringbacktone.pause();
          break;
        case CALL_MESSAGE_TYPE.ONNEWCALL:
          if (!checkSupportWebrtc()) {
            this.hangupWithReason('浏览器不支持WEBRTC');
            break;
          }
          // 判断是否已存在通话
          for (let item of Webrtc2Sip.instances.values()) {
            if (item.callStatus) {
              return;
            }
          }

          this.setRemoteSdp = false;
          this.isHalf = recvmsg.ishalf;
          this.isVideo = recvmsg.isvideo;
          this.remoteSdp = recvmsg.sdp;
          this.callDirection = CALL_DIRECTION.IN;
          this.ring();
          this.callStatus = true;
          this.ringtone.currentTime = 0;
          try {
            this.ringtone.play();
          } catch (error) {
            console.error('ringtone.play', error);
          }

          this.notify(recvmsg);
          break;
        case CALL_MESSAGE_TYPE.MEETUSERS:
          this.notify({ "type": recvmsg.type, "content": recvmsg.content });
          break;
      }
    };

    this.WS.onerror = ev => {
      console.error('WS.onerror', ev);
    };

    this.regStatus = false;

    this.PC = null;
    this.callStatus = false;
    this.isVideo = false;
    this.localStream = null;
    this.localElement = null;
    this.remoteElement = null;
    this.isHalf = false;
    this.callDirection = CALL_DIRECTION.OUT;
    this.remoteSdp = null;
    this.setRemoteSdp = false;

    this.ringbacktone = new Audio('/static/sounds/ringbacktone.wav');
    this.ringbacktone.loop = true;
    this.ringtone = new Audio('/static/sounds/ringtone.wav');
    this.ringtone.loop = true;
  }

  notify(content) {
    if (this.onMessage != null) {
      this.onMessage(content);
    }
  }

  onanswer(sdp) {
    if (!this.setRemoteSdp) {
      this.PC.setRemoteDescription(
        new RTCSessionDescription({
          type: 'answer',
          sdp: sdp,
        })
      );
      this.setRemoteSdp = true;
    }
  }

  onnewcall(sdp) {
    if (!this.setRemoteSdp) {
      this.PC.setRemoteDescription(
        new RTCSessionDescription({
          type: 'offer',
          sdp: sdp,
        })
      );
      this.setRemoteSdp = true;
    }
  }

  heart() {
    if (this.regStatus) {
      this.sendTo({ type: CALL_MESSAGE_TYPE.HEART, user_name: this.tel });
    }
  }

  login() {
    if (isWindows()) {
      this.sendTo({
        type: CALL_MESSAGE_TYPE.LOGIN,
        user_name: this.tel,
        pass_word: this.passwd,
        user_agent: 'windows',
      });
    } else {
      this.sendTo({
        type: CALL_MESSAGE_TYPE.LOGIN,
        user_name: this.tel,
        pass_word: this.passwd,
        user_agent: 'other',
      });
    }
  }

  logout() {
    this.regStatus = false;
    this.sendTo({ type: CALL_MESSAGE_TYPE.LOGOUT, user_name: this.tel });
  }

  dtmf(value) {
    if (!this.callStatus) {
      return false;
    }
    var dtmfAudio = new Audio('/static/sounds/dtmf.wav');
    dtmfAudio.play();
    this.sendTo({ type: CALL_MESSAGE_TYPE.DTMF, content: value });
    return true;
  }

  pttrequest() {
    if (!this.callStatus) {
      return false;
    }
    this.sendTo({ type: CALL_MESSAGE_TYPE.PTTREQUEST });
    return true;
  }

  pttrelease() {
    if (!this.callStatus) {
      return false;
    }
    this.sendTo({ type: CALL_MESSAGE_TYPE.PTTRELEASE });
    return true;
  }

  exit() {
    this.ringtone.pause();
    this.ringbacktone.pause();
    if (this.regStatus) {
      this.logout();
    }
    this.regStatus = false;
    this.callStatus = false;
    this.WS.close();
  }

  call(called, localElement, remoteElement, isVideo, isHalf) {
    let _this = this
    try {
      if (!this.regStatus) {
        console.log('user is not login');
        this.notify({
          type: CALL_MESSAGE_TYPE.MAKECALL,
          result: false,
          reason: '用户未登录',
        });
        return;
      }

      if (this.callStatus) {
        console.log('has in calling');
        this.notify({
          type: CALL_MESSAGE_TYPE.MAKECALL,
          result: false,
          reason: '已经在呼叫中',
        });
        return;
      }

      if (!checkSupportWebrtc()) {
        this.notify({
          type: CALL_MESSAGE_TYPE.MAKECALL,
          result: false,
          reason: '浏览器不支持WEBRTC',
        });
        return;
      }

      this.localElement = localElement;
      this.remoteElement = remoteElement;
      this.isVideo = isVideo;
      this.isHalf = isHalf;
      this.callStatus = true;
      this.callDirection = CALL_DIRECTION.OUT;
      this.setRemoteSdp = false;


      //通过RTCPeerConnection传输流媒体视频
      this.PC = new RTCPeerConnection(this.config);
      this.PC.onnegotiationneeded = () => {
        this.PC.createOffer().then(offer => {
          this.PC.setLocalDescription(offer);
        });
      };

      this.PC.onicecandidate = iceevent => {
        if (iceevent.candidate == null) {
          this.sendTo({
            type: CALL_MESSAGE_TYPE.MAKECALL,
            from: this.tel,
            to: called,
            sdp: this.PC.localDescription.sdp,
            ishalf: this.isHalf,
            isvideo: this.isVideo,
          });
        }
      };

      this.PC.ontrack = rtcTrackEvent => {
        if (_this.remoteElement != undefined) {
          // debugger
          _this.remoteElement.srcObject = rtcTrackEvent.streams[0];
          // _this.remoteElement.autoplay = true;
        }
      };

      if (isVideo && isHalf && localElement == null) {
        this.addTransceivers();
      } else {
        this.gotLocalMedia();
      }
    } catch (e) {
      this.callStatus = false;
      this.notify({
        type: CALL_MESSAGE_TYPE.MAKECALL,
        result: false,
        reason: '' + e,
      });
    }
  }

  answer(localElement, remoteElement) {
    this.localElement = localElement;
    this.remoteElement = remoteElement;
    this.PC = new RTCPeerConnection(this.config);

    this.PC.onnegotiationneeded = () => {
      this.onnewcall(this.remoteSdp);
      this.PC.createAnswer().then(answer => {
        this.PC.setLocalDescription(answer);
      });
    };

    this.PC.onicecandidate = iceevent => {
      if (iceevent.candidate == null) {
        this.sendTo({
          type: CALL_MESSAGE_TYPE.ANSWER,
          from: this.tel,
          sdp: this.PC.localDescription.sdp,
        });
      }
    };

    this.PC.ontrack = rtcTrackEvent => {
      if (this.remoteElement != undefined) {
        this.remoteElement.srcObject = rtcTrackEvent.streams[0];
        this.remoteElement.autoplay = true;
      }
    };
    try {
      this.ringtone.pause();
    } catch (error) { }

    this.gotLocalMedia();
  }

  hangup() {
    this.sendTo({
      type: CALL_MESSAGE_TYPE.HANGUP,
      from: this.tel,
    });
    this.closeCall();
    this.ringtone.pause();
    this.ringbacktone.pause();
  }

  hangupWithReason(reason) {
    this.sendTo({
      type: CALL_MESSAGE_TYPE.HANGUP,
      from: this.tel,
      reason: reason,
    });
    this.closeCall();
  }

  ring() {
    this.sendTo({
      type: CALL_MESSAGE_TYPE.RING,
      from: this.tel,
    });
  }

  sendTo(msg) {
    if (this.WSStatus) {
      console.log('send msg to server >>>>>>>>>>', msg);
      this.WS.send(JSON.stringify(msg));
    } else {
      console.log('wsstatus error, wsstatus: ', this.WSStatus);
    }
  }

  addTransceivers() {
    this.PC.addTransceiver('audio', {
      'direction': 'sendrecv'
    });

    this.PC.addTransceiver('video', {
      'direction': 'sendrecv'
    });
  }

  gotLocalMedia() {
    var config = {};
    if (this.isVideo) {
      config = {
        audio: { echoCancellation: true, noiseSuppression: true },
        video: { advanced: [{ height: 720, width: 1280 }] },
      };
    } else {
      config = {
        audio: { echoCancellation: true, noiseSuppression: true },
        video: false,
      };
    }

    if (navigator.getUserMedia) {
      navigator.getUserMedia(
        config,
        stream => {
          this.getMediaSucc(stream);
        },
        error => {
          this.getMediaFail(error);
        }
      );
    } else if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
      navigator.mediaDevices
        .getUserMedia(config)
        .then(stream => {
          this.getMediaSucc(stream);
        })
        .catch(error => {
          this.getMediaFail(error);
        });
    } else if (navigator.webkitGetUserMedia) {
      navigator.webkitGetUserMedia(
        config,
        stream => {
          this.getMediaSucc(stream);
        },
        error => {
          this.getMediaFail(error);
        }
      );
    } else if (navigator.mozGetUserMedia) {
      navigator.mozGetUserMedia(
        config,
        stream => {
          this.getMediaSucc(stream);
        },
        error => {
          this.getMediaFail(error);
        }
      );
    } else {
      if (this.callDirection === CALL_DIRECTION.OUT) {
        this.notify({
          type: CALL_MESSAGE_TYPE.MAKECALL,
          result: false,
          reason: '浏览器不支持WEBRTC',
        });
        this.closeCall();
      } else {
        this.notify({
          type: CALL_MESSAGE_TYPE.ANSWER,
          result: false,
          reason: '浏览器不支持WEBRTC',
        });
        this.hangupWithReason("can't get getUserMedia function");
        this.closeCall();
      }
    }
  }

  getMediaSucc(stream) {
    this.localStream = stream;
    if (this.isVideo && this.localElement != null) {
      this.localElement.srcObject = stream;
      this.localElement.muted = true;
    }

    stream.getTracks().forEach(track => {
      this.PC.addTrack(track, stream);
    });
  }

  getMediaFail(error) {
    console.log(error);
    if (this.callDirection === CALL_DIRECTION.OUT) {
      this.notify({
        type: CALL_MESSAGE_TYPE.MAKECALL,
        result: false,
        reason: '获取媒体资源失败',
      });
      this.closeCall();
    } else {
      this.notify({
        type: CALL_MESSAGE_TYPE.ANSWER,
        result: false,
        reason: '获取媒体资源失败',
      });
      this.hangupWithReason('getUserMedia function');
      this.closeCall();
    }
  }

  closeCall() {
    if (this.PC != null) {
      this.PC.close();
      this.PC = null;
      this.localElement = null;
      this.remoteElement = null;
      this.isVideo = false;
    }

    if (this.localStream != null) {
      this.localStream.getTracks().forEach(track => {
        this.localStream.removeTrack(track);
        track.stop();
      });
      this.localStream = null;
    }

    this.callStatus = false;
  }
}

function checkSupportWebrtc() {
  //check if the browser supports the WebRTC
  try {
    return !!(
      (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) ||
      navigator.getUserMedia ||
      navigator.webkitGetUserMedia ||
      navigator.mozGetUserMedia
    );
  } catch (e) {
    return false;
  }
}

function checkSupportWebsocket() {
  try {
    return !!window.WebSocket;
  } catch (e) {
    return false;
  }
}

function isWindows() {
  var useragnet = navigator.platform;
  return useragnet.indexOf('Win') >= 0;
}

export default Webrtc2Sip;
